#ifdef __arm__
#ifndef __aarch64__

.text
.align 5
.global ConvDwFp32Center
#ifndef __APPLE__
.type ConvDwFp32Center, %function
#endif

// void ConvDwFp32Center(float *dst, const float *src, const float *weight, const float *bias, size_t height, size_t width,
//                      size_t kernel_h, size_t kernel_w, size_t out_h_step, size_t block_channel, size_t in_sh_step, size_t in_sw_step,
//                      size_t in_kh_step, size_t in_kw_step, size_t relu, size_t relu6);
// r0: dst, r1: src, r2: weight, r3: bias, #48: height, #52: weight, #56: kernel_h, #60: kernel_w, 
// #64: out_h_step, #68: block_channel, #72: in_sh_step, #76: in_sw_step, #80: in_kh_step,#84: in_kw_step
// #88: relu, #92: relu6
ConvDwFp32Center:
    // at return, clang generates "push {lr}, pop {pc}"" while gcc will generate "bx lr"
    // according to https://stackoverflow.com/questions/53625807
    // even if we jump to link register instead of saving it, we still have to save it in subroutine calls anyway
    // clang's rule seems more simple, though there are no subroutine calls here
    // r4-r8 and q4-q7 must be saved according to https://static.docs.arm.com/ihi0042/i/aapcs32.pdf
    push {r0-r8, r10, r11, lr}

    ldr r4, [sp, #48]

    mov r12, #4
    ldr r8, [sp, #64]
    mul r8, r8, r12
    str r8, [sp, #64]
    ldr r8, [sp, #68]
    mul r8, r8, r12
    str r8, [sp, #68]
    ldr r8, [sp, #72]
    mul r8, r8, r12
    str r8, [sp, #72]
    ldr r8, [sp, #76]
    mul r8, r8, r12
    str r8, [sp, #76]
    ldr r8, [sp, #80]
    mul r8, r8, r12
    str r8, [sp, #80]
    ldr r8, [sp, #84]
    mul r8, r8, r12
    str r8, [sp, #84]
    mov r12, #16
    ldr r7, [sp, #60] // kernel_w
    mul r0, r7, r12

    vld1.32 q8, [r3]

    LoopH:
        ldr r1, [sp, #4] // src_w
        ldr r5, [sp, #52] // width
        ldr r3, [sp] // dst_w
        LoopW:
            mov r8, r1 // src_kh
            ldr r2, [sp, #8] // weight_kh
            ldr r6, [sp, #56] // kernel_h
            vld1.32 {q0}, [r3]
            vadd.f32 q0, q0, q8
            LoopKh:
                ldr r12, [sp, #84] //in_kw_step 
                ldr r7, [sp, #60] // kernel_w
                mov r10, r8 // src_kw
                mov r11, r2 // weight_kw
                LoopKw:
                    vld1.32 {q1}, [r10]
                    add r10, r10, r12
                    vld1.32 {q2}, [r11]!
                    vmla.f32 q0, q1, q2
                    subs r7, r7, #1
                    bne LoopKw
                ldr lr, [sp, #80]
                add r8, r8, lr
                add r2, r2, r0
                subs r6, r6, #1
                bne LoopKh
            ldr r12, [sp, #92]
            cmp r12, #0
            bne Relu6
            ldr r12, [sp, #88]
            cmp r12, #0
            bne Relu
            b Write
        Relu6:
            vmov.i32 q3, #6
            vcvt.f32.s32 q3, q3
            vmin.f32 q0, q0, q3
        Relu:
            veor q3, q3, q3
            vmax.f32 q0, q0, q3
        Write:
            ldr lr, [sp, #68]
            vst1.32 {q0}, [r3]
            add r3, r3, lr
            ldr lr, [sp, #76]
            add r1, r1, lr
            subs r5, r5, #1
            bne LoopW
        ldr lr, [sp, #64]
        ldr r12, [sp]
        add r12, r12, lr
        str r12, [sp]
        ldr lr, [sp, #72]
        ldr r12, [sp, #4]
        add r12, r12, lr
        str r12, [sp, #4]
        subs r4, r4, #1
        bne LoopH

    pop {r4-r8, r10, r11, pc}
#endif
#endif
